<script lang="ts" setup>
import { ref, computed, h, watch, onMounted, onBeforeMount, onBeforeUnmount } from 'vue'
import { useI18n } from 'vue-i18n'
import { TreeSelect, TreeSelectProps, CascaderProps, SelectProps } from 'ant-design-vue'
import ColumnSetting from '@/components/Table/src/components/settings/ColumnSetting.vue'
import { useColumn } from '@/components/Table/src/hooks/useColumn'
import { BasicPageParams, BasicTableColumn } from '@/types'
import { cloneDeep } from 'lodash-es'
import { isEmpty, isArray, isObject } from '@/utils/is'
import { getEnumDisplayName } from '@/utils/enum'

import * as roleApi from '@/api/modules/role'
import * as authApi from '@/api/modules/permission-temporary-authorization'
import * as signalR from '@/api/modules/interactive'

import router from '@/router'
import { createPermissionRouterGuard } from '@/router/guard/permissionGuard'

import { TYPE, useToast } from 'vue-toastification'
import { TimeUnit, timeUintOptions } from '@/types/modules/timeunit'

const toast = useToast()

const apiTreeData = ref<TreeSelectProps['treeData']>();
const tempRolePermissions = ref();
const step = ref();
const timeUnit = ref<TimeUnit>(TimeUnit.Minutes);

onBeforeMount(() => {
  signalR.default.attachToHub('PermissionTemporaryAuthorizationCallback', (record: any) => {
    if (record.data.status == 0) {
      createPermissionRouterGuard(router, true);
      toast(record.data.description, { timeout: 5000, type: TYPE.SUCCESS })
    } else {
      toast(record.data.description, { timeout: 5000, type: TYPE.ERROR })
    }
  });
})

onBeforeUnmount(() => {
  signalR.default.detachFromHub('PermissionTemporaryAuthorizationCallback')
  toast.dismiss('permission-temp-auth-callback')
})

onMounted(async () => {
  apiTreeData.value = await getApiPermissionsTreeData();
  step.value = 5;
  timeUnit.value = TimeUnit.Minutes;
})

const getApiPermissionsTreeData = async (): Promise<TreeSelectProps['treeData']> => {
  let perms = await roleApi.getApiPermissions();

  if (perms.data == undefined) {
    return;
  }

  let data = new Array<TreeSelectProps['treeData']>();

  perms.data.forEach(e => {
    let module = new Object();

    module.title = e.controllerDisplayName
    module.value = e.controller
    module.children = new Array<TreeSelectProps['treeData']>();

    for (let apiKey in e.apiInfo) {
      let api = new Object();
      api.title = e.apiInfo[apiKey];
      api.value = apiKey;

      module.children.push(api)
    }

    data.push(module)
  })

  return data as TreeSelectProps['treeData'];
}

const submit = async () => {  
  let requireContent = ''

  for (let idx = 0; idx < tempRolePermissions.value.length; idx++) {
    let node = apiTreeData.value?.find(x => x.value == tempRolePermissions.value[idx]);

    if (node === undefined) {
      apiTreeData.value?.forEach(e => {
        let temp = e.children?.find(x => x.value == tempRolePermissions.value[idx])

        if (temp !== undefined) {
          node = temp
        }
      })
    }

    if (idx == tempRolePermissions.value.length - 1) {            
      requireContent += node?.title;
    }
    else {
      requireContent += node?.title + '、';
    }    
  }  

  let key = await authApi.tryAcquireAsync(tempRolePermissions.value, requireContent, step.value, timeUnit.value);

  if (key !== null && key !== undefined) {
    toast('已发送临时授权申请', { timeout: 2000, type: TYPE.SUCCESS })
  }
}

const formatter = (value: number | string, info: { userTyping: boolean, input: string }): string => {
  if (info.userTyping) {
    value = unitChange(timeUnit.value)
  }
      
  return value.toString();
}

const unitChange = (value: number | string) => {
  if (timeUnit.value == TimeUnit.Minutes) {
    step.value = step.value > 59 ? 59 : step.value;
  } else if (timeUnit.value == TimeUnit.Hours) {
    step.value = step.value > 23 ? 23 : step.value;
  }
  else if (timeUnit.value == TimeUnit.Days) {
    step.value = step.value > 30 ? 30 : step.value;
  }

  return step.value;
}

</script>

<template>
<div class="page-wrapper">
  <a-card class="table-card">
    <span class="a-title">临时授权申请</span>
    <span>临时权限：</span>
    <TreeSelect v-model:value="tempRolePermissions" :tree-data="apiTreeData" tree-checkable allow-clear
      :show-checked-strategy="TreeSelect.SHOW_PARENT" placeholder="API权限" style="min-width: 200px; max-width: 400px;" />
    <div style="display: block; margin-top: 10px;">
      <span style="line-height: 32px;">申请时间：</span>
      <a-input-number v-model:value="step" style="width: 120px" :controls="false" :keyboard="false" :precision="0" :formatter="formatter">
        <template #addonAfter>
          <a-select v-model:value="timeUnit" style="width: 70px" @change="unitChange">
            <a-select-option :value="TimeUnit.Minutes">{{ getEnumDisplayName(TimeUnit.Minutes, timeUintOptions) }}</a-select-option>
            <a-select-option :value="TimeUnit.Hours">{{ getEnumDisplayName(TimeUnit.Hours, timeUintOptions) }}</a-select-option>
            <a-select-option :value="TimeUnit.Days">{{ getEnumDisplayName(TimeUnit.Days, timeUintOptions) }}</a-select-option>
          </a-select>
        </template>
      </a-input-number>
    </div>
    <a-button @click="submit" style="display: block; margin-top: 10px;">提交</a-button>
  </a-card>
</div>
</template>

<style lang="less" scoped>
.page-wrapper {
  padding: 20px;

  .table-card {
    margin-top: 20px;
  }
}

.drawer-footer {
  text-align: right;

  button {
    margin-left: 8px;
  }
}

.a-title {
  display: block;
  font-size: 1.5em;
  font-weight: 500;
  color: rgba(0, 0, 0, 0.85);
  margin-bottom: 2rem;
}
</style>
